package com.example.srb.core.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.srb.common.exception.Assert;
import com.example.srb.common.result.ResponseEnum;
import com.example.srb.core.enums.LendStatusEnum;
import com.example.srb.core.enums.TransTypeEnum;
import com.example.srb.core.hfb.FormHelper;
import com.example.srb.core.hfb.HfbConst;
import com.example.srb.core.hfb.RequestHelper;
import com.example.srb.core.mapper.*;
import com.example.srb.core.pojo.bo.TransFlowBO;
import com.example.srb.core.pojo.entity.Lend;
import com.example.srb.core.pojo.entity.LendItem;
import com.example.srb.core.pojo.entity.LendItemReturn;
import com.example.srb.core.pojo.entity.LendReturn;
import com.example.srb.core.service.*;
import com.example.srb.core.util.LendNoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 还款记录表 服务实现类
 * </p>
 *
 * @author Helen
 * @since 2021-02-20
 */
@Service
@Slf4j
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {

    @Resource
    private LendMapper lendMapper;
    @Resource
    private UserBindService userBindService;
    @Resource
    private LendItemReturnService lendItemReturnService;
    @Resource
    private UserAccountService userAccountService;
    @Resource
    private TransFlowService transFlowService;
    @Resource
    private UserAccountMapper userAccountMapper;
    @Resource
    private LendItemReturnMapper lendItemReturnMapper;
    @Resource
    private LendItemMapper lendItemMapper;

    @Override
    public List<LendReturn> selectByLendId(Long lendId) {
        QueryWrapper<LendReturn> wrapper = new QueryWrapper<>();
        wrapper.eq("lend_id",lendId);
        return baseMapper.selectList(wrapper);
    }

    @Override
    public String commitReturn(Long lendReturnId, Long userId) {

        //获取还款记录
        LendReturn lendReturn = baseMapper.selectById(lendReturnId);

        //判断账号余额是否充足
        BigDecimal account = userAccountService.getAccount(userId);
        Assert.isTrue(account.doubleValue() >= lendReturn.getTotal().doubleValue(),
                ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);

        //获取借款人code
        String bindCode = userBindService.getBindCodeByUserId(userId);
        Long lendId = lendReturn.getLendId();
        Lend lend = lendMapper.selectById(lendId);

        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);//给商户分配的唯一标识
        paramMap.put("agentGoodsName",lend.getTitle());//商品名称
        paramMap.put("agentBatchNo",lendReturn.getReturnNo());//批次号
        paramMap.put("fromBindCode",bindCode);//还款人绑定协议号
        paramMap.put("totalAmt",lendReturn.getTotal());//还款总额、
        paramMap.put("note","还款啦1111");//备注
        List<Map<String, Object>> lendItemReturnDetailList = lendItemReturnService.addReturnDetail(lendReturnId);
        paramMap.put("data", JSONObject.toJSONString(lendItemReturnDetailList));//还款明细数据
        paramMap.put("voteFeeAmt",new BigDecimal(0));//商户手续费
        paramMap.put("returnUrl",HfbConst.BORROW_RETURN_RETURN_URL);
        paramMap.put("notifyUrl",HfbConst.BORROW_RETURN_NOTIFY_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());//时间戳
        paramMap.put("sign",RequestHelper.getSign(paramMap));//验签参数

        return FormHelper.buildForm(HfbConst.BORROW_RETURN_URL,paramMap);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void notifyUrl(Map<String, Object> paramMap) {

        log.info("还款成功");

        String batchNo = (String) paramMap.get("agentBatchNo");
        //幂等性判断
        Boolean result = transFlowService.isSaveTransFlow(batchNo);
        if (result) {
            log.warn("幂等性返回");
            return;
        }

        //获取还款数据
        QueryWrapper<LendReturn> wrapper = new QueryWrapper<>();
        wrapper.eq("return_no",batchNo);
        LendReturn lendReturn = baseMapper.selectOne(wrapper);

        //更新还款状态
        lendReturn.setStatus(1);//状态（0-未归还 1-已归还）
        String voteFeeAmt = (String) paramMap.get("voteFeeAmt");//手续费
        lendReturn.setFee(new BigDecimal(voteFeeAmt));
        lendReturn.setRealReturnTime(LocalDateTime.now());
        baseMapper.updateById(lendReturn);

        //更新标的信息
        Lend lend = lendMapper.selectById(lendReturn.getLendId());
        //最后一次还款更新标的状态
        if (lendReturn.getLast()){
            lend.setStatus(LendStatusEnum.PAY_OK.getStatus());//更新为 还款结清 的状态
            lendMapper.updateById(lend);
        }

        //借款账号转出金额
        String bindCode = userBindService.getBindCodeByUserId(lend.getUserId());
        BigDecimal totalAmt = new BigDecimal((String) paramMap.get("totalAmt"));
        userAccountMapper.updateAccount(bindCode,totalAmt.negate(),new BigDecimal(0));

        //借款人交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                batchNo,
                bindCode,
                totalAmt,
                TransTypeEnum.RETURN_DOWN,
                "借款人还款扣减，项目编号：" + lend.getLendNo() + "   项目名称:" + lend.getTitle());
        transFlowService.saveTransFlow(transFlowBO);

        //获取回款计划
        List<LendItemReturn> lendItemReturnList = lendItemReturnService.selectLendItemReturnList(lendReturn.getId());
        lendItemReturnList.forEach( item -> {
            //更新回款状态
            item.setStatus(1);//状态（0-未归还 1-已归还）
            item.setRealReturnTime(LocalDateTime.now());
            lendItemReturnMapper.updateById(item);

            //更新投资记录
            LendItem lendItem = lendItemMapper.selectById(item.getLendItemId());
            lendItem.setRealAmount(lendItem.getRealAmount().add(item.getInterest()));//投资记录的 实际收益(利息)
            lendItemMapper.updateById(lendItem);

            //投资账号转入金额
            String investBindCode = userBindService.getBindCodeByUserId(item.getInvestUserId());
            userAccountMapper.updateAccount(investBindCode,item.getTotal(),new BigDecimal(0));

            //投资账号交易流水
            TransFlowBO flowBO = new TransFlowBO(
                    LendNoUtils.getReturnItemNo(),
                    investBindCode,
                    item.getTotal(),
                    TransTypeEnum.INVEST_BACK,
                    "还款到账，项目编号： " + lend.getLendNo() + "   项目名称:" + lend.getTitle());
            transFlowService.saveTransFlow(flowBO);

        });
    }
}
